﻿using System;
using System.Collections.Generic;
using System.Linq;
using Accord.Statistics.Analysis;
using TimbreRecognition.Extraction;


namespace TimbreRecognition.FeatureExtraction
{
    public class FeatureUtil
    {
        private const int NumberOfPCA = 12;

        private static PrincipalComponentAnalysis pca;

        public static List<DataItem> FeaturesToDataItems(List<Feature> features)
        {

            List<DataItem> dataItems = new List<DataItem>();
            foreach (Feature feature in features)
            {
                double[] data = new double[feature.MFCC.Length /* + 1 */];

                Array.Copy(feature.MFCC, data, feature.MFCC.Length);
              //  data[data.Length - 1] = feature.ZCR;

                DataItem dataItem = new DataItem
                {
                    DataSeries = data, 
                    ExpectedOutput = feature.ClassInfo
                };
                dataItems.Add(dataItem);
            }

            FeatureNormalizer featureNormalizer = FeatureNormalizer.GetInstance();
            List<DataItem> normilized = featureNormalizer.Normalize(dataItems);

           List<DataItem> principleComponents = ApplyPCA(normilized, NumberOfPCA);

           List<DataItem> normalizedComponents = featureNormalizer.NormalizeOnTheirRange(principleComponents);

           return principleComponents;
        }

        private static List<DataItem> ApplyPCA(List<DataItem> dataItems, int dimention)
        {

            List<double[]> data = dataItems.Select(o => o.DataSeries).ToList();

            if (pca == null)
            {

                double[][] sourceMatrix = new double[data.Count][];
                for (int i = 0; i < data.Count; i++)
                {
                    double[] sample = data[i];
                    sourceMatrix[i] = sample;
                }

                // Creates the Principal Component Analysis of the given source
                pca = new PrincipalComponentAnalysis(sourceMatrix, AnalysisMethod.Standardize);

                // Compute the Principal Component Analysis
                pca.Compute();
            }

            List<DataItem> pcaDataItems = new List<DataItem>();
            for (int i = 0; i < dataItems.Count; i++)
            {
                DataItem dataItem = new DataItem()
                {
                    DataSeries = pca.Transform(dataItems[i].DataSeries, dimention),
                    ExpectedOutput = dataItems[i].ExpectedOutput
                };
                pcaDataItems.Add(dataItem);
            }

            return pcaDataItems;
        }

    }
}
